import _ from 'lodash'

import { calculateSwitch } from '../../../tools/index'
import {
  PANEL_BATTLE_PADDING,
  BOARD_HEIGHT_SIZE,
  BOARD_WIDTH_SIZE
} from './config'
import type { ICardState } from './types'

export interface Context {
  get: Function
  getRect: Function
  self: Function
  getNode: Function
}

export class RenderMapping {
  data: Array<any> = []

  constructor() {
    // 页面元素构建表，根节点数组为一个面板
    // 尽可能减少功能损耗，禁止无意义刷新
    this.data = [
      this.buildBackgroundPanel(),
      this.buildBattleUnits()
    ]
  }

  buildBackgroundPanel() {
    return {
      type: 'static',
      // data用来注册计算属性，方便后续调用
      data: (state: Context) => {
        const rect = state.getRect('$root-rect')
        if (rect instanceof DOMRect) {
          const panelBattleHeight = state.get('panel-battle-height')
          const panelBottomHeight = state.get('panel-bottom-height')
          const width = rect.width
          const battleHeight = calculateSwitch(rect.height, panelBattleHeight)
          const bottomHeight = calculateSwitch(rect.height, panelBottomHeight)
          return {
            battleRect: new DOMRect(0, 0, width, battleHeight),
            bottomRect: new DOMRect(0, battleHeight, width, bottomHeight)
          }
        }
        return {
          battleRect: new DOMRect(),
          bottomRect: new DOMRect()
        }
      },
      children: [
        this.buildBattlePanel(),
        this.buildBottomPanel()
      ]
    }
  }

  buildBattlePanel() {
    return {
      rect: 'battle-rect',
      data: (state: Context) => {
        const rect = state.get('battle-rect')
        if (rect instanceof DOMRect) {
          const divider = 3
          const panelWidth = (rect.width - PANEL_BATTLE_PADDING * (divider + 1)) / divider
          const panelHeight = rect.height - PANEL_BATTLE_PADDING * 2
          const buildWidth = (index: number) => panelWidth * (index - 1) + PANEL_BATTLE_PADDING * index
          return {
            leftRect: new DOMRect(buildWidth(1), PANEL_BATTLE_PADDING, panelWidth, panelHeight),
            middleRect: new DOMRect(buildWidth(2), PANEL_BATTLE_PADDING, panelWidth, panelHeight),
            rightRect: new DOMRect(buildWidth(3), PANEL_BATTLE_PADDING, panelWidth, panelHeight)
          }
        }
        return {
          leftRect: new DOMRect(),
          middleRect: new DOMRect(),
          rightRect: new DOMRect()
        }
      },
      render: () => [
        {
          action: 'fill',
          params: {
            fill: '#1a1a1a'
          }
        }
      ],
      children: [
        this.buildBattleRoadPanel('left-rect'),
        this.buildBattleRoadPanel('middle-rect'),
        this.buildBattleRoadPanel('right-rect')
      ]
    }
  }

  buildBattleRoadPanel(name: string) {
    const render = (rect: DOMRect) => {
      const { width, height } = rect
      const lineSize = 2
      const dealRect = new DOMRect(lineSize, lineSize, width - 2 * lineSize, height - 2 * lineSize)
      return [
        {
          action: 'fill',
          params: {
            rect: dealRect,
            fill: '#1a1a1a'
          }
        },
        {
          action: 'stroke-rect',
          params: {
            rect: dealRect,
            strokeStyle: '#444',
            lineWidth: lineSize
          }
        }
      ]
    }

    return {
      rect: name,
      render: (state: Context) => render(state.getRect('$current-rect')),
      children: [this.buildBattleRoadUnitPanel('top'), this.buildBattleRoadUnitPanel('bottom')]
    }
  }

  buildBattleRoadUnitPanel(type: string) {
    const render = (rect: DOMRect) => {
      const { width, height } = rect
      const lineSize = 2

      const dealRect = new DOMRect(lineSize, lineSize, width - 2 * lineSize, height - 2 * lineSize)

      return [
        {
          action: 'fill',
          params: {
            rect: dealRect,
            fill: '#1a1a1a'
          }
        },
        {
          action: 'stroke-rect',
          params: {
            rect: dealRect,
            strokeStyle: '#555',
            lineWidth: lineSize,
            lineDash: [10, 10]
          }
        }
      ]
    }

    return {
      rect: (state: Context) => {
        const rect = state.getRect('$parent-rect')
        if (rect instanceof DOMRect) {
          const currentRect = DOMRect.fromRect(rect)
          const innerPadding = PANEL_BATTLE_PADDING * 5
          currentRect.height = (currentRect.height - innerPadding * 3) * 0.5
          let offsetTop = innerPadding
          if (type === 'bottom') {
            offsetTop += innerPadding + currentRect.height
          }
          currentRect.x = innerPadding
          currentRect.y = offsetTop
          currentRect.width -= 2 * innerPadding
          return currentRect
        }
        return rect
      },
      render: (state: Context) => render(state.getRect('$current-rect'))
    }
  }

  buildBottomPanel() {
    return {
      key: 'bottom-unit-panel',
      rect: 'bottom-rect',
      data: () => {
        const boardRectList = Array.from({ length: 5 })
        for (let x = 0; x < 5; x++) {
          const index = x
          const left = x * BOARD_WIDTH_SIZE
          const top = BOARD_HEIGHT_SIZE
          boardRectList[index] = new DOMRect(left, top, BOARD_WIDTH_SIZE, BOARD_HEIGHT_SIZE)
        }
        return { boardRectList }
      },
      render: () => [
        {
          action: 'fill',
          params: {
            fill: 'rgba(20, 0, 0, 0.7)'
          }
        }
      ]
    }
  }

  buildBattleUnits() {
    const render = (rect: DOMRect, item: ICardState, images: any) => {
      const { width, height } = rect
      const lineSize = 4
      const dealRect = new DOMRect(
        lineSize,
        lineSize,
        width - 2 * lineSize,
        height - 2 * lineSize
      )

      return [
        {
          action: 'fill-rect',
          params: {
            rect: dealRect,
            fill: '#aaa'
          }
        },
        {
          action: 'draw-image',
          params: {
            rect: dealRect,
            image: images[item.imagePath]
          }
        },
        {
          action: 'stroke-rect',
          params: {
            rect: dealRect,
            strokeStyle: '#666',
            lineWidth: lineSize
          }
        }
      ]
    }

    const nameRender = (rect: DOMRect, item: ICardState) => {
      const nameButton = document.createElement('div')
      nameButton.setAttribute('class', 'name-button')
      const name = document.createElement('div')
      name.textContent = item.name
      name.setAttribute('class', 'name-text')
      nameButton.appendChild(name)
      return nameButton
    }

    const glassMirrorRender = (rect: DOMRect) => {
      const mirror = document.createElement('div')
      mirror.setAttribute('class', 'card-mirror')
      return mirror
    }

    return {
      // 动态节点渲染
      type: 'dynamic',
      children: (state: any) => {
        const list = state.get('unit-list')
        return list.map((unit: ICardState) => ({
          key: `$unit-${unit.instanceId}`,
          pointer: true, // 鼠标选中时会索引
          ripple: true, // 鼠标点击时有波浪特效
          rect: (state: Context) => {
            const panelRect = state.getRect('bottom-unit-panel')
            if (panelRect instanceof DOMRect) {
              const { left, top } = panelRect
              return new DOMRect(
                left + unit.pointX,
                top + unit.pointY,
                BOARD_WIDTH_SIZE,
                BOARD_HEIGHT_SIZE
              )
            }
          },
          render: (state: Context) =>
            render(state.getRect('$current-rect'), unit, state.get('image-datas')),
          children: [
            {
              key: `$unit-${unit.instanceId}-name`,
              domRender: (state: Context) => nameRender(state.getRect('$current-rect'), unit)
            },
            {
              domRender: (state: Context) => glassMirrorRender(state.getRect('$current-rect'))
            }
          ]
        }))
      }
    }
  }

  // buildBattleEffects() {
  //   return {
  //     type: 'dynamic',
  //     children: (state: any) => {
  //       return state.effectsList.map((effects: any) => ({
  //         rect: `$node-rect-key-$unit-${effects.id}`,
  //         render: (state: Context) => { }
  //       }))
  //     }
  //   }
  // }
}
